package com.example.oneSpringMVC.service.impl;

import com.example.oneSpringMVC.dto.EmployeeDto;
import com.example.oneSpringMVC.dto.LoginDto;
import com.example.oneSpringMVC.dto.RandomNumDto;
import com.example.oneSpringMVC.entity.Employee;
import com.example.oneSpringMVC.entity.Permission;
import com.example.oneSpringMVC.exception.BusinessException;
import com.example.oneSpringMVC.mapper.EmployeeMapper;
import com.example.oneSpringMVC.mapper.PermissionMapper;
import com.example.oneSpringMVC.service.LoginService;
import com.example.oneSpringMVC.utils.RedisUtils;
import com.example.oneSpringMVC.utils.VerifyCodeUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import jakarta.servlet.http.HttpServletRequest;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: xinTong
 * @create: 2024-01-24 17:02
 **/
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public EmployeeDto select(LoginDto loginDto) throws JsonProcessingException {


        // 1 非法参数
        Assert.notNull(loginDto, "非法参数");
        // 2 校验验证码
        String verifyCode = redisUtils.get("VerifyCode:" + loginDto.getUuid());
        if (StringUtils.isEmpty(verifyCode)) {
            throw new BusinessException("验证码不存在！");
        }
        if (!VerifyCodeUtil.verification(loginDto.getCode(), verifyCode, true)) {
            throw new BusinessException("验证码输入错误！");
        }
        // 3 登录
        Employee loginEmployee = employeeMapper.select(loginDto.getUsername());
        // 4 校验登录逻辑
        if (ObjectUtils.isEmpty(loginEmployee)) {
            throw new BusinessException("姓名或密码输入错误！");
        }
        EmployeeDto employeeDto = employeeMapper.info(loginEmployee.getId());
        // 5 登录成功后，存储登录用户，存储相应的权限
        //将登录对象存储到session域对象
        ObjectMapper mapper = new ObjectMapper();
        String loginEmployeeJson = mapper.writeValueAsString(employeeDto);
        redisUtils.set("rbac:login_employee:" + employeeDto.getId(), loginEmployeeJson);
        //查询登录员工的权限
        List<Permission> permission = permissionMapper.queryPermission(loginEmployee.getId());
        List<String> expression = permission.stream().map(Permission::getExpression).collect(Collectors.toList());
        String expressionJson = mapper.writeValueAsString(expression);
        //将权限存储到session
        redisUtils.set("rbac:expression:" + loginEmployee.getId(), expressionJson);
        return employeeDto;
    }

    @Override
    public RandomNumDto code() {
        // 验证码 有两个属性 一个是图片/另一个是验证码
        // 工具类直接将其放入集合中
        // 可以用DTO进行封装，也可以直接返回map
        Map<String, String> map = VerifyCodeUtil.generateVerifyCode();

        String uuid = map.get("uuid");
        String code = map.get("code");

        RandomNumDto randomNumDto = new RandomNumDto();

        randomNumDto.setImg(map.get("img"));
        randomNumDto.setUuid(uuid);

        // key value timeout
        redisUtils.set("VerifyCode" + ":" + uuid, code, 3 * 60);
        return randomNumDto;
    }

    @Override
    public void loginOut(HttpServletRequest request) {

        // 清除redis登录数据
        String userId = request.getHeader("userId");
        Assert.notNull(userId, "非法参数");
        redisUtils.del("rbac:login_employee:" + userId);
        redisUtils.del("rbac:expression:" + userId);
    }
}
